package colibri.lcdui;

import colibri.App;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

/**
 *
 * @author Bayron Thiengo Quinelato
 */
public class ListItem extends Item {

    private String[][] items;
    private Image[][] icons;
    private int[] itemsX, itemsY, itemsMaxWidth, itemsAnchor;
    private int iconsX, iconsY, iconsAnchor;
    private int itemsLength, subItemsLength;
    private int itemHeight;
    private int itemsSpace;
    private int itemTop;
    private int index;
    private int maxVisibleItems;
    private int yOffset;
    private Image imBackgroundOut, imBackgroundIn;
    private int backgroundIn, backgroundOut;
    private static Font font;
    private int fontHeight;
    private int fontColorIn, fontColorOut;
    private boolean visibleArrows;
    private Image arrowUpOut, arrowUpIn, arrowDownOut, arrowDownIn;
    private boolean isArrowUpIn, isArrowDownIn;
    private int arrowUpHeight, arrowDownHeight;

    public ListItem(String[] items, int x, int y, int width, int height) {
        super(x, y, width, height);
        String[][] matrizTemp = new String[items.length][1];
        for (int i = 0; i < matrizTemp.length; i++) {
            matrizTemp[i][0] = items[i];
        }
        setProperties(matrizTemp);
    }

    public ListItem(String[][] items, int x, int y, int width, int height) {
        super(x, y, width, height);
        setProperties(items);
    }

    public void setItems(String[] items, int x, int y, int anchor) {
        if (items == null) {
            this.setItems(null);
            return;
        }
        String[][] matrizTemp = new String[items.length][1];
        for (int i = 0; i < matrizTemp.length; i++) {
            matrizTemp[i][0] = items[i];
        }
        items = null;
        this.setItems(matrizTemp);
    }

    public void setItems(String[][] items) {
        this.items = items;
        if (items != null && items.length > 0) {
            itemsLength = items.length;
            subItemsLength = items[0].length;
        } else {
            itemsLength = 0;
            subItemsLength = 0;
        }
        if (itemsX == null || itemsX.length != subItemsLength) {
            itemsX = new int[subItemsLength];
            itemsY = new int[subItemsLength];
            itemsMaxWidth = new int[subItemsLength];
            itemsAnchor = new int[subItemsLength];
            for (int i = 0; i < subItemsLength; i++) {
                if (i == 0) {
                    itemsX[i] = width / 2;
                    itemsAnchor[i] = Graphics.TOP | Graphics.HCENTER;
                } else {
                    itemsX[i] = 10;
                    itemsAnchor[i] = Graphics.TOP | Graphics.LEFT;
                }
                itemsY[i] = 5 + i * (fontHeight + 5);
                itemsMaxWidth[i] = width - 20;
            }
        }
        itemTop = 0;
        index = 0;
        itemsSpace = 10;
        setItemHeight(-1);
    }

    public void setIcons(Image[] icons, int x, int y, int anchor) {
        if (icons == null) {
            return;
        }
        Image[][] matrizTemp = new Image[icons.length][1];
        for (int i = 0; i < matrizTemp.length; i++) {
            matrizTemp[i][0] = icons[i];
        }
        icons = null;
        this.setIcons(matrizTemp, x, y, anchor);
    }

    public void setIcons(Image[][] icons, int x, int y, int anchor) {
        if (icons == null) {
            return;
        }
        this.icons = icons;
        this.iconsX = x;
        this.iconsY = y;
        this.iconsAnchor = anchor;
    }

    private void setProperties(String[][] items) {
        font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
        fontHeight = font.getHeight();
        fontColorIn = 0x666666;
        fontColorOut = 0xCCCCCC;
        visibleArrows = false;
        arrowUpHeight = 0;
        arrowDownHeight = 0;
        setItems(items);
    }

    protected void callPaint(Graphics g) {
        if ((items == null || itemsLength <= 0) && (icons == null || icons.length <= 0)) {
            return;
        }

        // Desenha os items
        if (items != null && itemsLength > 0) {
            int itemY = y + yOffset + arrowUpHeight;
            for (int i = itemTop; i < itemTop + maxVisibleItems; i++) {
                if (i == index) {
                    if (imBackgroundIn == null) {
                        g.setColor(backgroundIn);
                        g.fillRoundRect(x, itemY, width, itemHeight, 10, 10);
                    } else {
                        g.drawImage(imBackgroundIn, x, itemY, Graphics.TOP | Graphics.LEFT);
                    }
                    g.setColor(fontColorIn);
                } else {
                    if (imBackgroundOut == null) {
                        g.setColor(backgroundOut);
                        g.fillRoundRect(x, itemY, width, itemHeight, 10, 10);
                    } else {
                        g.drawImage(imBackgroundOut, x, itemY, Graphics.TOP | Graphics.LEFT);
                    }
                    g.setColor(fontColorOut);
                }
                for (int j = 0; j < subItemsLength; j++) {
                    if (font.stringWidth(items[i][j]) > itemsMaxWidth[j]) {
                        g.drawSubstring(items[i][j], 0, itemsMaxWidth[j], x + itemsX[j], itemY + itemsY[j], itemsAnchor[j]);
                    } else {
                        g.drawString(items[i][j], x + itemsX[j], itemY + itemsY[j], itemsAnchor[j]);
                    }
                }
                itemY += (itemHeight + itemsSpace);
            }
        }

        // Desenha os icons
        if (icons != null && icons.length > 0) {
            int itemY = y + yOffset + arrowUpHeight;
            for (int i = itemTop; i < itemTop + maxVisibleItems; i++) {
                if (i == index) { 
                    if (icons[i].length >= 2 && icons[i][1] != null) {
                        g.drawImage(icons[i][1], x + iconsX, itemY + iconsY, iconsAnchor);
                    } else if (icons[i][0] != null) {
                        g.drawImage(icons[i][0], x + iconsX, itemY + iconsY, iconsAnchor);
                    }
                } else {
                    if (icons[i][0] != null) {
                        g.drawImage(icons[i][0], x + iconsX, itemY + iconsY, iconsAnchor);
                    }
                }
                itemY += (itemHeight + itemsSpace);
            }
        }

        // Desenha as setas
        if (visibleArrows) {
            if (itemTop > 0) {
                if (isArrowUpIn && arrowUpIn != null) {
                    g.drawImage(arrowUpIn, x + width / 2, y + 2, Graphics.TOP | Graphics.HCENTER);
                } else if (arrowUpOut != null) {
                    g.drawImage(arrowUpOut, x + width / 2, y + 2, Graphics.TOP | Graphics.HCENTER);
                }
            }
            if (itemTop < (itemsLength - maxVisibleItems)) {
                if (isArrowDownIn && arrowDownIn != null) {
                    g.drawImage(arrowDownIn, x + width / 2, y + height - 2, Graphics.BOTTOM | Graphics.HCENTER);
                } else if (arrowDownOut != null) {
                    g.drawImage(arrowDownOut, x + width / 2, y + height - 2, Graphics.BOTTOM | Graphics.HCENTER);
                }
            }
        }
    }

    private void makeSelectedVisible() {
        if (index >= 0) {
            if (index <= itemTop) {
                itemTop = index;
            } else if (index - itemTop + 1 > maxVisibleItems) {
                itemTop = index - maxVisibleItems + 1;
            }
        }
    }

    public void setItemHeight(int itemHeight) {
        if (itemHeight > 0) {
            this.itemHeight = itemHeight;
        } else {
            if (imBackgroundOut == null && imBackgroundIn == null) {
                if (subItemsLength > 1) {
                    if ((itemsAnchor[0] & Graphics.TOP) != 0) {
                        this.itemHeight = subItemsLength * (fontHeight + 5) + 2 * itemsY[0];
                    } else if ((itemsAnchor[0] & Graphics.BASELINE) != 0 || (itemsAnchor[0] & Graphics.BOTTOM) != 0) {
                        this.itemHeight = subItemsLength * (fontHeight + 5) + 2 * (itemsY[0] - fontHeight);
                    } else if ((itemsAnchor[0] & Graphics.VCENTER) != 0) {
                        this.itemHeight = subItemsLength * (fontHeight + 5) + 2 * (itemsY[0] - fontHeight / 2);
                    }
                } else {
                    this.itemHeight = fontHeight + 10;
                }
            } else if (imBackgroundOut == null) {
                this.itemHeight = imBackgroundIn.getHeight();
            } else if (imBackgroundIn == null) {
                this.itemHeight = imBackgroundOut.getHeight();
            } else {
                this.itemHeight = imBackgroundOut.getHeight();
                if (imBackgroundIn.getHeight() > this.itemHeight) {
                    this.itemHeight = imBackgroundIn.getHeight();
                }
            }
        }
        setMaxVisibleItems();
    }

    private void setMaxVisibleItems() {
        if (itemHeight + itemsSpace > 0) {
            maxVisibleItems = (height - arrowUpHeight - arrowDownHeight) / (itemHeight + itemsSpace);
            yOffset = ((height - arrowUpHeight - arrowDownHeight) % (itemHeight + itemsSpace));
            if (yOffset >= itemHeight) {
                maxVisibleItems++;
                yOffset -= itemHeight;
            }
            yOffset = yOffset / 2;
            if (maxVisibleItems > itemsLength) {
                maxVisibleItems = itemsLength;
            }
        }
    }

    public void setSelectedItem(String item) {
        if (items == null) {
            return;
        }
        for (int i = 0; i < itemsLength; i++) {
            if (item.equalsIgnoreCase(items[i][0])) {
                index = i;
                break;
            }
        }
        makeSelectedVisible();
    }

    public String getSelectedItem() {
        if (items == null) {
            return null;
        } else {
            return items[index][0];
        }
    }

    public void setIndexItem(int index) {
        this.index = index;
        makeSelectedVisible();
    }

    public int getIndexItem() {
        return index;
    }

    public void setFont(Font font) {
        ListItem.font = font;
        fontHeight = font.getHeight();
        setItemHeight(-1);
    }

    public static Font getFont() {
        if (font == null) {
            return Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
        }
        return font;
    }

    public void setColorItem(int colorOut, int colorIn) {
        this.fontColorOut = colorOut;
        this.fontColorIn = colorIn;
    }

    public void setBackground(int colorOut, int colorIn) {
        this.backgroundOut = colorOut;
        this.backgroundIn = colorIn;
    }

    public void setBackground(Image imOut, Image imIn) {
        this.imBackgroundOut = imOut;
        this.imBackgroundIn = imIn;
        setItemHeight(-1);
        if (imBackgroundOut != null && imBackgroundIn == null) {
            width = imBackgroundOut.getWidth();
        } else if (imBackgroundOut == null && imBackgroundIn != null) {
            width = imBackgroundIn.getWidth();
        } else if (imBackgroundOut != null && imBackgroundIn != null) {
            width = imBackgroundOut.getWidth();
            if (imBackgroundIn.getWidth() > width) {
                width = imBackgroundIn.getWidth();
            }
        }
    }

    public void setItemsSpace(int itemsSpace) {
        this.itemsSpace = itemsSpace;
        setMaxVisibleItems();
    }

    public int getItemsSpace() {
        return itemsSpace;
    }

    public int getItemsHeight() {
        return itemHeight;
    }

    public void setItemsX(int[] itemsX) {
        if (itemsX == null || itemsX.length == 0) {
            return;
        }
        this.itemsX = itemsX;
    }

    public void setItemsY(int[] itemsY) {
        if (itemsY == null || itemsY.length == 0) {
            return;
        }
        this.itemsY = itemsY;
        setItemHeight(-1);
    }

    public void setItemsMaxWidth(int[] itemsMaxWidth) {
        if (itemsMaxWidth == null || itemsMaxWidth.length == 0) {
            return;
        }
        this.itemsMaxWidth = itemsMaxWidth;
    }

    public void setItemsAnchor(int[] itemsAnchor) {
        if (itemsAnchor == null || itemsAnchor.length == 0) {
            return;
        }
        this.itemsAnchor = itemsAnchor;
        setItemHeight(-1);
    }

    public void setVisibleArrows(boolean visibleArrows) {
        this.visibleArrows = visibleArrows;
        setArrowsHeight();
    }

    public boolean isVisibleArrows() {
        return this.visibleArrows;
    }

    private void setArrowsHeight() {
        // Define a altura das setas
        if (visibleArrows) {
            if (arrowUpOut != null && arrowUpIn != null) {
                if (arrowUpOut.getHeight() > arrowUpIn.getHeight()) {
                    arrowUpHeight = arrowUpOut.getHeight() + 10;
                } else {
                    arrowUpHeight = arrowUpIn.getHeight() + 10;
                }
            } else if (arrowUpOut != null) {
                arrowUpHeight = arrowUpOut.getHeight() + 10;
            } else {
                arrowUpHeight = 0;
            }
            if (arrowDownOut != null && arrowDownIn != null) {
                if (arrowDownOut.getHeight() > arrowDownIn.getHeight()) {
                    arrowDownHeight = arrowDownOut.getHeight() + 10;
                } else {
                    arrowDownHeight = arrowDownIn.getHeight() + 10;
                }
            } else if (arrowDownOut != null) {
                arrowDownHeight = arrowDownOut.getHeight() + 10;
            } else {
                arrowDownHeight = 0;
            }
            setMaxVisibleItems();
        } else {
            arrowUpHeight = 0;
            arrowDownHeight = 0;
        }
    }

    public void setArrows(Image arrowUp, Image arrowDown) {
        if (arrowUp == null || arrowDown == null) {
            arrowUpHeight = 0;
            arrowDownHeight = 0;
            return;
        }
        arrowUpOut = arrowUp;
        arrowUpIn = null;
        arrowDownOut = arrowDown;
        arrowDownIn = null;
        setArrowsHeight();
    }

    public void setArrows(Image arrowUpOut, Image arrowUpIn, Image arrowDownOut, Image arrowDownIn) {
        if (arrowUpOut == null || arrowUpIn == null || arrowDownOut == null || arrowDownIn == null) {
            arrowUpHeight = 0;
            arrowDownHeight = 0;
            return;
        }
        this.arrowUpOut = arrowUpOut;
        this.arrowUpIn = arrowUpIn;
        this.arrowDownOut = arrowDownOut;
        this.arrowDownIn = arrowDownIn;
        setArrowsHeight();
    }

    private void up() {
        if (index > 0) {
            index--;
            makeSelectedVisible();
        }
    }

    private void down() {
        if (index < itemsLength - 1) {
            index++;
            makeSelectedVisible();
        }
    }

    protected void callKeyPressed(int keyCode) {
        int gameAction = App.getGameAction(keyCode);
        switch (gameAction) {
            case App.UP:
                isArrowUpIn = true;
                break;
            case App.DOWN:
                isArrowDownIn = true;
                break;
            default:
                break;
        }
    }

    protected void callKeyReleased(int keyCode) {
        isArrowUpIn = false;
        isArrowDownIn = false;
        int gameAction = App.getGameAction(keyCode);
        switch (gameAction) {
            case App.UP:
                up();
                break;
            case App.DOWN:
                down();
                break;
        }
    }

    protected void callKeyRepeated(int keyCode) {
        int gameAction = App.getGameAction(keyCode);
        switch (gameAction) {
            case App.UP:
                up();
                break;
            case App.DOWN:
                down();
                break;
        }
    }

    protected void callPointerPressed(int x, int y) {
        if (x > this.x && x < this.x + width && y > this.y && y < this.y + arrowUpHeight) {
            isArrowUpIn = true;
        } else if (x > this.x && x < this.x + width && y > this.y + height - arrowDownHeight && y < this.y + height) {
            isArrowDownIn = true;
        } else if (x > this.x && x < this.x + width && y > this.y + yOffset + arrowUpHeight && y < this.y + height) {
            for (int i = 0; i < maxVisibleItems; i++) {
                if (y > this.y + arrowUpHeight + i * (itemHeight + itemsSpace) && y < this.y + yOffset + arrowUpHeight + (i + 1) * (itemHeight + itemsSpace) - itemsSpace) {
                    index = itemTop + i;
                    makeSelectedVisible();
                    break;
                }
            }
        }
    }

    protected void callPointerReleased(int x, int y) {
        isArrowUpIn = false;
        isArrowDownIn = false;
        if (x > this.x && x < this.x + width && y > this.y && y < this.y + arrowUpHeight) {
            if (visibleArrows) {
                up();
            }
        } else if (x > this.x && x < this.x + width && y > this.y + height - arrowDownHeight && y < this.y + height) {
            if (visibleArrows) {
                down();
            }
        }
    }

    protected void callPointerDragged(int x, int y) {
        isArrowUpIn = false;
        isArrowDownIn = false;
    }
}
